package com.lemon.boot.common.utils;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.lemon.boot.common.exception.CustomException;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * 码生成工具类
 */
@Slf4j
public final class CodeUtil {
    /**
     * 生成二维码
     *
     * @param url
     * @param width
     * @param height
     * @return
     */
    public static byte[] qrcode(String url, int width, int height) {
        Map<EncodeHintType, Object> hashMap = new HashMap<>(16);
        //设置二维码字符编码
        hashMap.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        //设置二维码纠错等级
        hashMap.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
        //设置二维码边距
        hashMap.put(EncodeHintType.MARGIN, 1);

        try {
            //开始生成二维码
            BitMatrix bitMatrix = new MultiFormatWriter().encode(url, BarcodeFormat.QR_CODE, width, height, hashMap);
            ByteArrayOutputStream pngOutputStream = new ByteArrayOutputStream();
            MatrixToImageWriter.writeToStream(bitMatrix, "png", pngOutputStream);
            return pngOutputStream.toByteArray();
        } catch (WriterException | IOException e) {
            log.error("CodeUtil.qrcode.message:{}", e.getMessage());
            throw new CustomException(e.getMessage());
        }
    }

    /**
     * 验证码图片
     *
     * @param width
     * @param height
     * @param codeCount
     * @param lineCount
     * @return
     */
    public static Captcha captchaCode(int width, int height, int codeCount, int lineCount) {
        //1.设置验证码的宽度、高度、验证码位数、lineNoiseLevel噪声水平
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(width, height, codeCount, lineCount);

        //2.获取生成的验证码文本
        String code = lineCaptcha.getCode();

        //3.获取生成的图片
        BufferedImage image = lineCaptcha.getImage();

        //4.将BufferedImage转换为字节数组，以便进行网络传输或者文件输出
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

        try {
            ImageIO.write(image, "png", outputStream);
        } catch (IOException e) {
            log.error("CodeUtil.captchaCode.message:{}", e.getMessage());
            throw new CustomException(e.getMessage());
        }

        Captcha captcha = new Captcha();
        captcha.setCode(code);
        captcha.setBytes(outputStream.toByteArray());
        return captcha;
    }

    /**
     * 响应图片
     *
     * @param url
     * @param width
     * @return
     */
    public static ResponseEntity<byte[]> responseQrEntity(String url, int width) {
        byte[] qrcode = qrcode(url, width, width);
        
        //设置头部信息
        final HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.IMAGE_PNG);

        return new ResponseEntity<>(qrcode, headers, HttpStatus.OK);
    }

    /**
     * 验证码图片
     */
    @Setter
    @Getter
    public static class Captcha {
        private String code;
        private byte[] bytes;
    }
}
